#pragma once

using namespace System::Collections::Generic;

namespace SpikingNeuronLib
{
	/// Generate all combinations of size 'groupSize' from a group of size 'numElementsToCombine'
	// Computationally equivalent to the following (where groupSize is fixed at 3):
	//    for i in 0..numElementsToCombine-1 do
	//        for j in i..numElementsToCombine-1 do
	//            for k in j..numElementsToCombine-1 do
	//                if i <> j && j <> k then
	//                    yield i, j, k
	// but allows group sized to be programmatically defined
	public ref class CombinationGenerator
	{
	protected:
		int _groupSize;					// the size of each group of combinations
		int _numElementsToCombine;		// the size of the pool that combinations are sampled from
		array<int>^ _combinations;

		static array<int>^ InitializeCombinations(int groupSize);
		static bool GetNextCombinations(bool continueCombining, array<int>^ combinations, int groupSize, int numElementsToCombine);

	public:
		CombinationGenerator(int groupSize, int numElementsToCombine);

		// return the current combination
		property array<int>^ Current
		{
			array<int>^ get()
			{
				return _combinations;
			}
		}

		void ReinitializeCombinations();
		bool GetNextCombinations(bool continueCombining);

		// Get all combinations of the specified size from a larger group with the specified number of elements
		static List<array<int>^>^ GetCombinations(int groupSize, int numElementsToCombine);
	};
}
